package org.wsocket;

import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.wsocket.Exception.WSocketException;
import org.wsocket.config.Config;
import org.wsocket.config.WSocketLoader;
import org.wsocket.connector.Connector;
import org.wsocket.container.Container;
import org.wsocket.flashbridge.FlashBridge;
import org.wsocket.message.Message;
import org.wsocket.socketset.SocketSet;
import org.wsocket.socketset.SocketSetManager;
import org.wsocket.thread.HandShakeMessageTask;
import org.wsocket.thread.SendMessageTask;
import org.wsocket.thread.ThreadPool;

public class WSocket {
	private Listener listener = null;
	private static Config config = new Config();
	private FlashBridge flashBirdge;
	private ConcurrentHashMap<String, SocketSet> allSocketSets = new ConcurrentHashMap<String, SocketSet>();
	
	public static int getAllSocketSetSize() {
		return config.getSocketSetSize();
	}

	public static ConcurrentHashMap<String, SocketSet> getAllSocketSets() {
		return WSocket.getInstance().allSocketSets;
	}

	public static int getDefaultTimeOut(){
		return config.getSocketTimeOut();
	}
	
	public static int getThreadPoolSize(){
		return config.getThreadPoolSize();
	}
	
	public static int getPortSizes(){
		return config.getPorts().length;
	}

	private WSocket() {
		initConfig();
		initInstance();
	}

	private void initConfig() {
		config = WSocketLoader.getConfig();
	}

	private void initInstance() {
		for (int i = 0; i < config.getSocketSetSize(); i++) {
			SocketSet ss = new SocketSet(i + "");
			allSocketSets.put(ss.getKey(), ss);
			ss.start();
		}
		
		//for (int i = 0; i < config.getPorts().length; i++) {
			SocketSetManager ssm = new SocketSetManager(config.getPorts());
			ssm.start();
		//}
		this.flashBirdge = new FlashBridge();
	}

	public static Connector getConnector(String connectorKey) {
		if (!(connectorKey != null && connectorKey.indexOf("_") > 0)) {
			return null;
		}
		String setKey = connectorKey.substring(0, connectorKey.indexOf("_"));

		return ((SocketSet) (WSocket.getInstance().allSocketSets.get(setKey)))
				.getConector(connectorKey);
	}

	public static Container getContainer(String ID) {
		return null;
	}

	public static void broadCast(String message, String fromKey) throws WSocketException{
		Set<String> keySet = WSocket.getInstance().allSocketSets.keySet();
		for (String socketkey : keySet) {
			WSocket.getInstance().allSocketSets.get(socketkey).broadCast(
					message, fromKey);
		}
	}

	public static void setListener(Listener CusListener) {
		WSocket.getInstance().listener = CusListener;
	}

	public static Listener getListener() {
		return WSocket.getInstance().listener;
	}

	/**
	 * Following inner class implements the singleton without thread safety
	 * issues.
	 */
	private static final class WSocketHolder {
		private static WSocket theSingleton = new WSocket();

		public static WSocket getSingleton() {
			return theSingleton;
		}

		private WSocketHolder() {
		}
	}

	/**
	 * Gets the only instance of the WSocket
	 * 
	 * @return the single instance of WSocket
	 */
	public static WSocket getInstance() {
		return WSocket.WSocketHolder.getSingleton();
	}
	
	public static void sendMessage(Connector target, String message) throws WSocketException {
		SendMessageTask task = new SendMessageTask(new Message(null, target,
				message));
		ThreadPool.assginTask(task);
	}
	
	public static void sendMessage(Container target, String message) throws WSocketException{
		target.broadcast(message);
	}

}
